package com.kvn.universal.core.multistep;

import com.kvn.universal.core.Invoker;
import com.kvn.universal.core.InvokerBuilder;
import com.kvn.universal.core.InvokerContext;
import com.kvn.universal.core.idempotent.IdempotentContext;
import com.kvn.universal.core.idempotent.IdempotentStep;
import com.kvn.universal.core.idempotent.StepsContainer;
import com.kvn.universal.core.lock.LockContext;
import com.kvn.universal.core.lock.LockHolder;
import com.kvn.universal.dao.IIdempotentDao;
import com.kvn.universal.filter.FilterFactory;
import com.kvn.universal.filter.idempotent.IdempotentHolder;

/**
 * 幂等中含有多步骤的测试
 * 
 * @author wzy
 * @date 2017年10月11日 下午2:14:08
 */
public class BizMulitiStepsService {
	
	private IIdempotentDao idempotentDao;
	public BizMulitiStepsService(IIdempotentDao idempotentDao) {
		super();
		this.idempotentDao = idempotentDao;
	}
	
	public String doBiz(final String param){
		InvokerContext context = InvokerContext.create().apendArg(param);
		IdempotentHolder holder = IdempotentHolder.create("幂等key-step1", "33", "23");
		context.putExtendContext(IdempotentContext.create(holder));
		Invoker bizInvoker1 = new Invoker() {
			@Override
			public Object invoke(InvokerContext invokerContext) {
				return step1(param);
			}
		};
		
		final String rlt1 = (String) InvokerBuilder
				.buildInvoker(bizInvoker1, context, FilterFactory.createIdempodentFilter(idempotentDao))
				.delegateInvokeInvoker();
		
		
		
		IdempotentHolder holder2 = IdempotentHolder.create("幂等key-step2", "33", "23");
		context.putExtendContext(IdempotentContext.create(holder2));
		Invoker bizInvoker2 = new Invoker() {
			@Override
			public Object invoke(InvokerContext invokerContext) {
				return step2(param, invokerContext);
			}
		};
		
		String rlt2 = (String) InvokerBuilder
				.buildInvoker(bizInvoker2, context, FilterFactory.createIdempodentFilter(idempotentDao))
				.delegateInvokeInvoker();
		
		
		IdempotentHolder holder3 = IdempotentHolder.create("幂等key-step3", "33", "23");
		context.putExtendContext(IdempotentContext.create(holder3));
		Invoker bizInvoker3 = new Invoker() {
			@Override
			public Object invoke(InvokerContext invokerContext) {
				return step3(param);
			}
		};
		
		String rlt3 = (String) InvokerBuilder
				.buildInvoker(bizInvoker3, context, FilterFactory.createIdempodentFilter(idempotentDao))
				.delegateInvokeInvoker();
		
		
		return "OK";
	}
	
	/**
	 * 新的分步幂等方式
	 * @param param
	 * @return
	 */
	public String doBizNew(final String param){
		InvokerContext context = InvokerContext.create().apendArg(param);
		context.putExtendContext(LockContext.create().appendLock(LockHolder.create("wzy")));
		Invoker bizInvoker = new Invoker() {
			@Override
			public Object invoke(InvokerContext invokerContext) {
				return multistep(param);
			}

		};
		
		return (String) InvokerBuilder
				.buildInvoker(bizInvoker, context, FilterFactory.createLockFilter())
				.delegateInvokeInvoker();
		
	}
	
	private String multistep(final String param) {
		IdempotentHolder holder1 = IdempotentHolder.create("幂等key-new", "业务1", "step1");
		IdempotentHolder holder2 = IdempotentHolder.create("幂等key-new", "业务1", "step2");
		IdempotentHolder holder3 = IdempotentHolder.create("幂等key-new", "业务1", "step3");
		IdempotentStep step1 = new IdempotentStep(holder1) {
			@Override
			public Object invoke(InvokerContext invokerContext) {
				String step1rlt = step1(param);
				return step1rlt;
			}
		};
		IdempotentStep step2 = new IdempotentStep(holder2) {
			@Override
			public Object invoke(InvokerContext invokerContext) {
				return step2(param, invokerContext);
			}
		};
		IdempotentStep step3 = new IdempotentStep(holder3) {
			@Override
			public Object invoke(InvokerContext invokerContext) {
				return step3(param);
			}
		};
		StepsContainer.create(idempotentDao).addStep(step1).addStep(step2).addStep(step3).executeAll(InvokerContext.create());
		
		return "OK";
	}

	private String step3(String param) {
		System.out.println("执行step3，参数：param=" + param);
		return "step3OK";
	}

	private String step2(String param, InvokerContext context) {
		IdempotentContext idempotentContext = context.getExtendContext(IdempotentContext.class);
		String rlt1 = (String) idempotentContext.getStepRltList().get(0);
		System.out.println("执行step2，参数：param=" + param + ", rlt1=" + rlt1);
		return "step2OK";
//		throw new RuntimeException("step2异常");
	}

	private String step1(String param) {
		System.out.println("执行step1，参数：param=" + param);
		return "step1OK";
	}

	/**
	 * 全新的接口（最佳实践）
	 * @param string
	 */
	public void doBizNew2(final String param) {
		IdempotentStep step1 = new IdempotentStep(IdempotentHolder.create("幂等key-new", "业务1", "step1")) {
			@Override
			public Object invoke(InvokerContext invokerContext) {
				String step1rlt = step1(param);
				return step1rlt;
			}
		};
		IdempotentStep step2 = new IdempotentStep(IdempotentHolder.create("幂等key-new", "业务1", "step2")) {
			@Override
			public Object invoke(InvokerContext invokerContext) {
				return step2(param, invokerContext);
			}
		};
		IdempotentStep step3 = new IdempotentStep(IdempotentHolder.create("幂等key-new", "业务1", "step3")) {
			@Override
			public Object invoke(InvokerContext invokerContext) {
				return step3(param);
			}
		};
		
		// 1. 不用锁的写法
		StepsContainer.create(idempotentDao).addStep(step1).addStep(step2).addStep(step3).executeAll(InvokerContext.create());
		
		// 2. 用锁的写法
//		InvokerContext context = InvokerContext.create();
//		context.putExtendContext(LockContext.create().appendLock(LockHolder.create("wzy")));
//		StepsWithinLockContainer.create(idempotentDao).addStep(step1).addStep(step2).addStep(step3).executeAll(context);
	}

}
